import { SerialPort, SerialPortOpenOptions } from 'serialport'

class SerialPortQueue {
  private port: SerialPort | null = null
  private queue: { data: Buffer; status: 'ready' | 'success' | 'error' }[] = []
  private isSending = false
  private shouldContinue = true
  private sentCount = 0
  private queueStatus: string = 'ready'
  private previousQueueStatus: string[] = []
  private timeOut: number = 3000 // 设置超时时间，单位毫秒
  private timeOutTimers: NodeJS.Timeout[] = []

  async openPort(portName: string, baudRate: number): Promise<void> {
    const options: SerialPortOpenOptions<Buffer> = { path: portName, baudRate }
    this.port = new SerialPort(options)

    this.port.on('open', () => {
      console.log('Serial port opened.')
      this.processQueue()
    })

    this.port.on('error', (err) => {
      console.error('Serial port error:', err)
      this.updateQueueStatus('error')
      this.stopQueue()
    })
  }

  async closePort(): Promise<void> {
    if (this.port) {
      return new Promise((resolve, reject) => {
        this.port?.close((err) => {
          if (err) {
            reject(err)
          } else {
            this.port = null
            resolve()
          }
        })
      })
    } else {
      return Promise.resolve()
    }
  }

  enqueueMessage(data: Buffer): void {
    this.queue.push({ data, status: 'ready' })
    if (!this.isSending) {
      this.processQueue()
    }
  }

  private processQueue(): void {
    if (this.port && this.queue.length > 0 && !this.isSending && this.shouldContinue) {
      this.isSending = true
      const currentMessage = this.queue[0]
      const remainingQueue = this.queue.slice(1)
      this.port.write(currentMessage.data, (err) => {
        if (err) {
          console.error('Error sending message:', err)
          this.updateMessageStatus(currentMessage, 'error')
          this.shouldContinue = false
          this.updateQueueStatus('error')
          this.stopQueue()
        } else {
          const timeOutTimer = setTimeout(() => {
            this.updateMessageStatus(currentMessage, 'error')
            this.shouldContinue = false
            this.updateQueueStatus('error')
            this.stopQueue()
          }, this.timeOut)
          this.timeOutTimers.push(timeOutTimer)
          this.port?.on('data', (data) => {
            if (this.validateResponse(data)) {
              clearTimeout(timeOutTimer)
              this.updateMessageStatus(currentMessage, 'success')
              this.sentCount++
              if (this.sentCount === this.queue.length) {
                // 所有指令发送且校验成功，清空指令列表
                this.queue = []
                this.sentCount = 0
                this.updateQueueStatus('completed')
              } else {
                this.queue = remainingQueue
              }
              this.isSending = false
              this.processQueue()
            }
          })
        }
      })
    }
  }

  // 假设的校验函数
  validateResponse(message: Buffer): boolean {
    // 根据实际情况进行校验逻辑实现
    return true
  }

  getQueueStatus(): string {
    return this.queueStatus
  }

  getPreviousQueueStatuses(): string[] {
    return this.previousQueueStatus
  }

  private updateQueueStatus(status: string): void {
    this.previousQueueStatus.push(this.queueStatus)
    this.queueStatus = status
  }

  private updateMessageStatus(
    message: { data: Buffer; status: 'ready' | 'success' | 'error' },
    newStatus: 'success' | 'error'
  ): void {
    message.status = newStatus
  }

  stopQueue(): void {
    this.shouldContinue = false
    this.timeOutTimers.forEach((timer) => clearTimeout(timer))
  }

  restartQueue(): void {
    this.shouldContinue = true
    this.sentCount = 0
    this.queue.forEach((item) => (item.status = 'ready'))
    this.timeOutTimers = []
    this.processQueue()
  }

  goToPreviousStep(): void {
    if (this.sentCount > 0) {
      this.sentCount--
      this.shouldContinue = true
      const previousMessage = this.queue[this.sentCount]
      previousMessage.status = 'ready'
      this.timeOutTimers.forEach((timer) => clearTimeout(timer))
      this.timeOutTimers = []
      this.processQueue()
    }
  }

  goToNextStep(): void {
    if (this.sentCount < this.queue.length) {
      const currentMessage = this.queue[this.sentCount]
      currentMessage.status = 'ready'
      this.sentCount++
      this.shouldContinue = true
      this.processQueue()
    }
  }
}

export default SerialPortQueue
